package com.ztf.controller;

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.client.naming.utils.ThreadLocalRandom;
import com.ztf.openfeign.NacosServiceFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/user")
public class NacosClientController {

    @RequestMapping("/test")
    public String test(){
        return "nacos-service test";
    }

    @Autowired
    private RestTemplate restTemplate;

    //普通实现方式
    @RequestMapping("/call")
    public String call(){
        // java.net.HttpURLConnection   HttpClient   OkHttp   RestTemplate   Feign    Socket
        // http://localhost:9091/order/query 可能是多变的
        return restTemplate.getForObject("http://localhost:8884/order/query",String.class);
    }

    @Resource
    private DiscoveryClient discoveryClient;


    // 表示服务发现
    @RequestMapping("/getinstances1")
    public List<ServiceInstance> getinstances1(){
        return discoveryClient.getInstances("nacos-service");
    }

    @Autowired
    private NacosServiceManager nacosServiceManager;

    @Autowired
    private NacosDiscoveryProperties nacosDiscoveryProperties;

//    @NacosInjected
//    private NamingService namingService;

    // 表示服务发现
    @RequestMapping("/getinstances")
    public List<Instance> getinstances(){
        NamingService namingService = null;
        try {
            if(namingService ==null){
                namingService = nacosServiceManager.getNamingService(nacosDiscoveryProperties.getNacosProperties());
            }
            return namingService.getAllInstances("nacos-service");
        } catch (NacosException e) {
            e.printStackTrace();
        }
        return null;
    }


    // 人工实现负载均衡
    @RequestMapping("/balanceTest")
    public String test1(){
        // discoveryClient.getInstances("order-service");--->urls--->url
        // restTemplate进行调用
        //  "uri": "http://192.168.1.3:9092,9091",
        List<ServiceInstance> instances = discoveryClient.getInstances("nacos-service");
        List<String> uris = instances.stream().
                map(instance -> instance.getUri().toString() + "/order/query").collect(Collectors.toList());
        // 使用随机的负载均衡算法得到一个uri
        int index= ThreadLocalRandom.current().nextInt(uris.size());
        String url=uris.get(index);
        return restTemplate.getForObject(url,String.class);
    }

    @Resource
    private LoadBalancerClient loadBalancerClient;   // 从Spring IoC容器中获取该类的实现类

    // 使用Ribbon实现负载均衡
    // 实现负载均衡
    // Ribbon: 服务发现+负载均衡
    @RequestMapping("/ribbonTest")
    public String ribbonTest(){
        // Ribbon的API使用方式   默认使用的轮询的负载均衡算法
        ServiceInstance serviceInstance = loadBalancerClient.choose("nacos-service");
        String url = serviceInstance.getUri().toString() + "/order/query";
        return restTemplate.getForObject(url,String.class);
    }

    // Ribbon的其他使用方式+RestTemplate：强耦合的
    @Resource
    private RestTemplate ribbonRestTemplate;

    @RequestMapping("/ribbonRestTemplateTest")
    public String ribbonRestTemplateTest(){
        return this.ribbonRestTemplate.getForObject("http://nacos-service/order/query",String.class);
    }

    // 思考：http://order-service/order/query   更加倾向于：Object#method

    // 使用OpenFeign进行远程调用
    @Resource
    private NacosServiceFeignClient nacosServiceFeignClient;

    @RequestMapping("/testopenfeign")
    public String testopenfeign(){
        // TODO: 该方法不是没有实现吗？   --->类比MyBatis    UserMapper直接使用？    配置了sql语句，底层帮你生成了动态代理实现类
        return nacosServiceFeignClient.query();
    }



}